#include "parser.h"

int
count (string s, char c)
{
  int n = 0;
  for (int i = 0; i < s.length (); i++)
    if (s[i] == c)
      n++;
  return n;
}

string
quotestring (string s)
{
  return string("\"") + s + string("\"");
}

string
format (string s)
{
  return "format";
}

Object*
parse (string expr)
{
  // Check length
  if (expr.length () == 0)
    return new Error ("Empty expression: expr.length () == 0",
		      "core/parser.cpp:parse", 0, 31);
  // Quoted case
  if (expr[0] == '\'')
    {
      List* temp = new List ();
      temp->insert (new Symbol ("quote"));
      if (expr[1] == '(' && expr[2] == ')')
	temp->append (nil);
      else
	temp->append (parse (expr.substr (1)));
      return temp;
    }
  // List case
  else if (count (expr, '(') > 0)
    return parseList (expr);
  // Atom case
  return parseAtom (expr);
}

Object*
parseAtom (string expr)
{
  // ToDo: write up isInteger, isDecimal, isRational in core/utility
  if (expr[0] == '\"')
    if (expr[expr.length ()-1] == '\"')
      return new String (expr.substr (1, expr.length () - 2));
    else
      return new String (expr.substr (1));
  //else if (isInteger (expr) || isDecimal (expr) || isRational (expr))
  //  return new Number (expr);
  return new Symbol (expr);
}

Object*
parseList (string expr)
{
  if (expr[0] == '(')
    if (expr.length () == 2 && expr[expr.length ()-1] == ')')
      return new Error ("Empty expression: ()",
			"core/parser.cpp:parseList", 0, 65);
    else
      expr = expr.substr (1, expr.length ()-2);
  List* exprList = new List ();
  list<string> tokens = tokenize (expr);
  string buffer = "";
  bool subExpression = false;
  int bracketCount = 0, length = 0;
  //cout << "tokens.size: " << tokens.size () << endl;
  for (list<string>::iterator token = tokens.begin ();
       token != tokens.end (); token++)
    {
      //cout << "token: " << *token << endl;
      length = token->length ();
      if (length == 0)
	continue;

      if (token->find ('(') != string::npos)
	{
	  subExpression = true;
	  bracketCount++;
	}
      if ((*token)[0] == ')' || (length >= 1 && (*token)[length-1] == ')'))
	bracketCount -= (length - token->find (')'));

      if (subExpression)
	{
	  if (bracketCount == 0)
	    {
	      if (buffer.length () == 0)
		exprList->append (parse (*token));
	      else
		exprList->append (parse (buffer + *token));
	      subExpression = false;
	      buffer = "";
	    }
	  else
	    buffer += *token + " ";
	}
      else
	exprList->append (parse (*token));
    }
  return exprList;
}
